'use strict';
let _ = new Object();

module.exports = Object.assign(_, {
  // bytes
  b: 1,
  kb: 1 << 10,
  mb: 1 << 20,
  gb: 1 << 30,
  schema: (schema) => {
    let args = arguments;
    delete args[0];
    for (let item in args) {
      if (typeof args[item] != 'object')
        return;
      for (let key in args[item]) {
        if (!(schema[key].type.indexOf(typeof args[item][key]) > -1))
          delete args[item][key];
      }
    }
  },
  filter_deffrent: (data, origin, schema) => {
    let object = {};
    for (let key in schema) {
      if ((typeof data[key] == schema[key].type) && (data[key] != origin[key]))
        object[key] = data[key];
    }
    Object
      .keys(object)
      .length || (object = false);
    return object;
  },
  exclude_repeat(obj, schema) {
    let repeat = {};
    for (let key in schema) {
      if (schema[key].norepeat && obj[key])
        repeat[key] = obj[key];
    }
    if (Object.keys(repeat).length)
      return repeat;
    return null;
  },
  // 排除唯一字段
  excludedEliminate: (obj, col, skip) => {
    if (!obj)
      return Promise.resolve('ok');
    return new Promise((resolve, reject) => {
      let query = {};
      if (skip) {
        let $ne = {};
        for (let key in skip) {
          $ne[key] = {
            $ne: skip[key]
          };
        }
        Object.assign(query, $ne);
      }
      let $or = [];
      for (let key in obj) {
        $or.push({
          [key]: obj[key] });
      }
      query['$or'] = $or;
      global
        .mongo
        .find(col, { query: query })
        .then(docs => {
          if (docs.length) {
            docs.forEach(doc => {
              for (let key in obj) {
                if (doc[key] == obj[key]) {
                  reject(global.apiError(400, `${key} has been used`));
                  return;
                }
              }
            });
          }
          resolve('ok');
        })
        .catch(e => {
          reject(e);
        });
    });
  },
  clone: function(schema) {
    let obj = new Object();
    let args = arguments;
    delete args[0];
    for (let key in args) {
      if ((typeof args[key] == 'object') && (args[key].constructor != Array)) {
        for (let skey in args[key]) {
          obj[skey] = args[key][skey];
        }
      }
    }
    _.schema(schema, obj);
    return obj;
  },
  jsonurlencode: (json, isencode) => {
    if (typeof json == 'object') {
      let arr = new Array;
      for (let key in json) {
        arr.push(key + '=' + (isencode ?
          encodeURIComponent(json[key]) :
          json[key]));
      }
      let str = arr.join('&');
      return str;
    } else {
      let err = new Error('first argument must a json');
      throw err;
    }
  },
  urldecodejson: (str, isdecode) => {
    if (typeof str == 'string') {
      isdecode
        ?
        str = decodeURIComponent(str) :
        str;
      let arr = str.split('&');
      let json = {};
      for (let i in arr) {
        if (typeof arr[i] == 'string') {
          let temp = arr[i];
          let index = temp.indexOf('=');
          json[temp.substr(0, index)] = temp.substr(index + 1);
        }
      }
      return json;
    } else {
      let err = new Error('first argument must a urlencode string');
      throw err;
    }
  },
  // 复制对象参数
  extend: (from, to, schema) => {
    let object = to || new Object();
    let check = schema || from;
    for (let key in check) {
      if ((typeof from[key] == 'object') && !(from[key] instanceof Array)) {
        object[key] = _.extend(from[key], object[key]);
      } else if (schema) {
        if (schema[key]) {
          if ((!from[key]) && schema[key].default) {
            typeof schema[key].default == 'function' ?
              (object[key] = schema[key].default()) :
              (object[key] = schema[key].default);
          } else if (schema[key].type.indexOf(typeof from[key]) > -1) {
            object[key] = from[key];
          }
        }
      } else if (!from[key]) {
        continue;
      } else {
        object[key] = from[key];
      }
    }
    return object;
  },
  // 判断两个数组是否有交集
  a_b: (a, b) => {
    let l,
      s;
    if (a.length > b.length)
      l = a,
      s = b;
    else
      l = b,
      s = a;
    let flag = false;
    for (let i = 0; i < s.length; i++) {
      if (l.has(s[i])) {
        flag = true;
        break;
      }
    }
    return flag;
  },
  // 排除参数
  exclude: (object, array) => {
    array.forEach(key => {
      if (object[key])
        delete object[key];
    });
    return object;
  },
  // 扁平化json
  delayering: (json) => {
    let obj = new Object();
    for (let key in json) {
      if (typeof json[key] == 'object')
        Object.assign(obj, _.delayering(json[key]));
      obj[key] = json[key];
    }
    return obj;
  },
  maskEmail: (email) => {
    let result = /^([\w\.]+)(@.+)$/.exec(email);
    if (!result) {
      return '***';
    }
    let str = result[1];
    let len = str.length > 2 ?
      2 :
      str.length - 1;
    return str.substr(0, len) + '****' + result[2];
  },
  maskMobile: (mobile) => {
    let result = /^(\d{3})\d{4}(\d{4})$/.exec(mobile);
    if (!result) {
      return '***';
    }
    return result[1] + '****' + result[2];
  },
  testEmail: (email) => {
    let flag = true;
    (!emailReg.test(email)) ?
    flag = false: flag = true;
    return flag;
  },
  testMobile: (mobile) => {
    let flag = true;
    (!mobileReg.test(mobile)) ?
    flag = false: flag = true;
    return flag;
  },
  testID: (idNumber) => {
    idNumber = idNumber + '';
    let flag = true;
    city[idNumber.substr(0, 2)] ?
      flag = true :
      flag = false;
    (isIDCard1.test(idNumber)) ?
    flag = true: flag = false;
    (isIDCard2.test(idNumber)) && isTrueValidateCodeBy18IdCard(idNumber) ?
      flag = true :
      flag = false;
    return flag;
  }
});

// 邮箱正则表达式
const emailReg = /^([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+\.[a-zA-Z]{2,3}$/;

// 手机号正则表达式
const mobileReg = /^(13[0-9]|14[0-9]|15[0-9]|17[0-9]|18[0-9])\d{8}$/;

// 身份证正则表达式(15位)
const isIDCard1 = /^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$/;
// 身份证正则表达式(18位)
const isIDCard2 = /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{4}$/;
// 身份证加权因子
const Wi = [
  7,
  9,
  10,
  5,
  8,
  4,
  2,
  1,
  6,
  3,
  7,
  9,
  10,
  5,
  8,
  4,
  2,
  1
];
// 身份证验证位值.10代表X
const ValideCode = [
  1,
  0,
  10,
  9,
  8,
  7,
  6,
  5,
  4,
  3,
  2
];
// 身份证省份编码
const city = {
  11: '北京',
  12: '天津',
  13: '河北',
  14: '山西',
  15: '内蒙古',
  21: '辽宁',
  22: '吉林',
  23: '黑龙江 ',
  31: '上海',
  32: '江苏',
  33: '浙江',
  34: '安徽',
  35: '福建',
  36: '江西',
  37: '山东',
  41: '河南',
  42: '湖北 ',
  43: '湖南',
  44: '广东',
  45: '广西',
  46: '海南',
  50: '重庆',
  51: '四川',
  52: '贵州',
  53: '云南',
  54: '西藏 ',
  61: '陕西',
  62: '甘肃',
  63: '青海',
  64: '宁夏',
  65: '新疆',
  71: '台湾',
  81: '香港',
  82: '澳门',
  91: '国外'
};
// 18位身份证需要验证最后一位校验位
function isTrueValidateCodeBy18IdCard(code) {
  let flag = true;
  code = code.split('');
  let sum = 0;
  let ai = 0;
  let wi = 0;
  for (let i = 0; i < 17; i++) {
    ai = code[i];
    wi = Wi[i];
    sum += ai * wi;
  }
  ValideCode[sum % 11] == code[17] ?
    flag = true :
    flag = false;
  return flag;
}
